package com.jtw.conf.shiro.util;

import com.jtw.conf.shiro.CustomAuthorizationFilter;
import com.jtw.conf.shiro.CustomShiroConf;
import com.jtw.conf.shiro.model.BasePerm;
import com.jtw.conf.shiro.model.FilterPerm;
import com.jtw.conf.shiro.service.BasePermService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.NamedFilterList;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ShiroUtil {

    public static final String FilterKey = CustomAuthorizationFilter.FilterKey;

    /**
     * 导入拦截配置（这里从数据库中获取），适用于写死之后
     * 该方法用于shiro初始化时，之后无效
     *
     * @param shiroFilterFactoryBean
     */
    public static void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean,
                                            BasePermService basePermService) {
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // authc: 需要认证 (org.apache.shiro.web.filter.authc.FormAuthenticationFilter)
        //        // anon: 不需要认证(等同不拦截)

        List<FilterPerm> allPerm = basePermService.getAllPerm();


        for (FilterPerm filterPerm : allPerm) {
            if (filterPerm.getOpen()) continue;
            filterChainDefinitionMap.put(filterPerm.getUrl(), filterPerm.getFilterString(FilterKey));
        }

        // 静态资源不作拦截
        filterChainDefinitionMap.put("/static/**", "anon");
        // 其他的访问不作拦截
        filterChainDefinitionMap.put("/**", "anon");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    }


    /**
     * 更新shiro权限配置
     * 适用于shiro初始化之后
     *
     * @param shiroFilterFactoryBean
     * @param basePermService
     * @throws Exception
     */
    public static void updateFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean,
                                         BasePermService basePermService) throws Exception {
        log.info("初始化系统shiro权限核心配置--->开始");
        AbstractShiroFilter abstractShiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
        FilterChainResolver filterChainResolver = abstractShiroFilter.getFilterChainResolver();
        PathMatchingFilterChainResolver pathMatchingFilterChainResolver = (PathMatchingFilterChainResolver) filterChainResolver;
        DefaultFilterChainManager defaultFilterChainManager = (DefaultFilterChainManager) pathMatchingFilterChainResolver.getFilterChainManager();

        Map<String, NamedFilterList> defaultFilterChains = defaultFilterChainManager.getFilterChains();
        defaultFilterChainManager.getFilterChains().clear();
        if (defaultFilterChainManager != null) {
            defaultFilterChainManager.getFilterChains().putAll(defaultFilterChains);
        }

        List<FilterPerm> allPerm = basePermService.getAllPerm();
        for (FilterPerm filterPerm : allPerm) {
            addToChain(defaultFilterChainManager, filterPerm);
        }


        /**
         * 其他未设置的/sys/**路径都必须是登陆可用
         */
        defaultFilterChainManager.addToChain("/sys/**", CustomShiroConf.PRIVATE_REQUEST_URL_PERMISSION);
        defaultFilterChainManager.addToChain("/member/**", CustomShiroConf.PRIVATE_REQUEST_URL_PERMISSION);

        defaultFilterChainManager.addToChain("/static/**", CustomShiroConf.PUBLIC_REQUEST_URL_PERMISSION);
        /**
         * 最后添加其他未设置的/**路径都不拦截
         */
        defaultFilterChainManager.addToChain("/**", CustomShiroConf.PUBLIC_REQUEST_URL_PERMISSION);
        log.info("初始化系统shiro权限核心配置--->完毕");
    }

    private static void addToChain(DefaultFilterChainManager defaultFilterChainManager, FilterPerm filterPerm) {
        if (filterPerm.getOpen()!=null&&filterPerm.getOpen()) {
            //公共方法
            defaultFilterChainManager.addToChain(filterPerm.getUrl(), CustomShiroConf.PUBLIC_REQUEST_URL_PERMISSION);
            log.info(filterPerm.getUrl() + " ----> "+ CustomShiroConf.PUBLIC_REQUEST_URL_PERMISSION);
        } else {
            //其他的都需要权限
            defaultFilterChainManager.addToChain(filterPerm.getUrl(), FilterKey, filterPerm.getFilterString());
            log.info(filterPerm.getUrl() + " ----> " + filterPerm.getFilterString());

        }
    }
}
